package cn.edu.hnu.gpg.service;

import cn.edu.hnu.gpg.dao.StudentDocMapper;
import cn.edu.hnu.gpg.dao.UploadedFileMapper;
import cn.edu.hnu.gpg.dto.StudentDocumentInfo;
import cn.edu.hnu.gpg.entity.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class StudentDocServiceImpl implements StudentDocService{

    private StudentDocMapper studentDocMapper;
    private final StudentService studentService;
    private final UploadedFileMapper uploadedFileMapper;
    private final UploadedFileService uploadedFileService;

    @Autowired
    public StudentDocServiceImpl(StudentDocMapper studentDocMapper, StudentService studentService, UploadedFileService uploadedFileService, UploadedFileMapper uploadedFileMapper){
        this.studentDocMapper = studentDocMapper;
        this.studentService = studentService;
        this.uploadedFileService = uploadedFileService;
        this.uploadedFileMapper = uploadedFileMapper;
    }

    @Override
    public boolean gradeStudentDoc(StudentDoc studentDoc) {
        if (studentDoc == null)
            return false;

        return  studentDocMapper.insertSelective(studentDoc) > 0;
    }

    @Override
    public Integer createOrReplace(String dirPath, String fileName, MultipartFile file, Integer studentId, Integer phaseId) throws IOException {

        // 检查是否已存在
        StudentDocExample example = new StudentDocExample();
        example.or()
                .andStudentIdEqualTo(studentId)
                .andPhaseIdEqualTo(phaseId);

        List<StudentDoc> studentDocList = studentDocMapper.selectByExample(example);
        if (studentDocList.isEmpty()) {
            // 上传新文件
            Integer uploadedFileId = uploadedFileService.uploadFile(dirPath, fileName, file , studentService.findStudentByStudentId(studentId).getUserId());
            StudentDoc studentDoc = new StudentDoc();
            studentDoc.setUploadedFileId(uploadedFileId);
            studentDoc.setStudentId(studentId);
            studentDoc.setPhaseId(phaseId);
            return studentDocMapper.insertSelective(studentDoc);
        } else {
            uploadedFileService.replaceFile(dirPath, studentDocList.get(0).getUploadedFileId(), fileName, file);
            return studentDocList.get(0).getUploadedFileId();
        }
    }

    @Override
    public StudentDocumentInfo queryDocumentInfo(Integer fileId) {

        StudentDoc studentDoc = studentDocMapper.selectByPrimaryKey(fileId);
        UploadedFile uploadedFile = uploadedFileService.queryFileInfo(fileId);

        if (studentDoc == null || uploadedFile == null)
            return null;

        StudentDocumentInfo documentInfo = new StudentDocumentInfo(studentDoc);
        documentInfo.setFileName(uploadedFile.getFileName());

        return documentInfo;
    }

    @Override
    public List<StudentDocumentInfo> listDocumentByStudentId(Integer studentId) {

        Student student = studentService.findStudentByStudentId(studentId);

        StudentDocExample studentDocExample = new StudentDocExample();
        studentDocExample.or().andStudentIdEqualTo(studentId);
        studentDocExample.setOrderByClause("`phase_id` ASC");
        List<StudentDoc> studentDocList = studentDocMapper.selectByExample(studentDocExample);

        UploadedFileExample uploadedFileExample = new UploadedFileExample();
        uploadedFileExample.or().andUploaderEqualTo(student.getUserId());
        List<UploadedFile> uploadedFileList = uploadedFileMapper.selectByExample(uploadedFileExample);

        return mergeStudentDocInfoAndUploadFile(studentDocList, uploadedFileList);
    }

    @Override
    public List<StudentDocumentInfo> listDocumentByUserId(Integer userId) {

        Student student = studentService.findStudentByUserId(userId);

        StudentDocExample studentDocExample = new StudentDocExample();
        studentDocExample.or().andStudentIdEqualTo(student.getStudentId());
        studentDocExample.setOrderByClause("`phase_id` ASC");
        List<StudentDoc> studentDocList = studentDocMapper.selectByExample(studentDocExample);

        UploadedFileExample uploadedFileExample = new UploadedFileExample();
        uploadedFileExample.or().andUploaderEqualTo(userId);
        List<UploadedFile> uploadedFileList = uploadedFileMapper.selectByExample(uploadedFileExample);

        return mergeStudentDocInfoAndUploadFile(studentDocList, uploadedFileList);
    }

    private List<StudentDocumentInfo> mergeStudentDocInfoAndUploadFile(List<StudentDoc> studentDocList, List<UploadedFile> uploadedFileList) {

        if (studentDocList == null || uploadedFileList == null)
            return new ArrayList<>();

        if (studentDocList.size() != uploadedFileList.size())
            throw new IllegalArgumentException("Two lists must share the size");

        List<StudentDocumentInfo> infoList = new ArrayList<>(studentDocList.size());
        for (UploadedFile file : uploadedFileList) {
            for (StudentDoc studentDoc : studentDocList) {
                if (studentDoc.getUploadedFileId().equals(file.getUploadedFileId())) {
                    StudentDocumentInfo documentInfo = new StudentDocumentInfo(studentDoc);
                    documentInfo.setFileName(file.getFileName());
                    infoList.add(documentInfo);
                    break;
                }
            }
        }
        return infoList;
    }

    @Override
    public boolean gradeStudentDoc(int upload_file_id, int uploader, int score, @Nullable String comment, int phase_id) {
        if (upload_file_id < 0 || uploader < 0)
            return false;

        StudentDoc studentDoc = new StudentDoc();
        studentDoc.setUploadedFileId(upload_file_id);
        studentDoc.setComments(comment);
        studentDoc.setPhaseId(phase_id);
        studentDoc.setStudentId(uploader);
        return studentDocMapper.insertSelective(studentDoc) >0 ;
    }

    @Override
    public boolean deleteByDocId(int studentDoc_Id) {
        if(studentDoc_Id < 1)
            return false;

        return studentDocMapper.deleteByPrimaryKey(studentDoc_Id) > 0;
    }
}
